from fastapi import File, HTTPException
from datetime import datetime
from oss2 import Auth, Bucket, exceptions, SizedFileAdapter
from io import BytesIO
from PIL import Image
from core.Log import log_admin_event

from .Config import ALIYUN_ACCESS_KEY_ID, ALIYUN_ACCESS_KEY_SECRET, ALIYUN_OSS_ENDPOINT, ALIYUN_OSS_BUCKET_NAME, UPLOAD_PATH, STATIC_PREFIX, PART_SIZE

auth = Auth(ALIYUN_ACCESS_KEY_ID, ALIYUN_ACCESS_KEY_SECRET)
bucket = Bucket(auth, ALIYUN_OSS_ENDPOINT, ALIYUN_OSS_BUCKET_NAME)

class PartInfo:
    def __init__(self, part_number, etag, size, part_crc = None):
        self.part_number = part_number
        self.etag = etag
        self.size = size
        self.part_crc = part_crc

async def upload_file(file: File(...)):
    try:
        # 生成文件路径，确保不以 `/` 开头
        file_extension = file.filename.split(".")[-1]
        file_extension = file_extension.lstrip(".").lower()
        timestamp = datetime.now().strftime("%Y%m%d%H%M%S%f")
        new_filename = f"{timestamp}.{file_extension}"
        # file_name = f"{UPLOAD_PATH}/{datetime.now().strftime('%Y-%m-%d')}/{file.filename.lstrip('/')}"
        file_name = f"{UPLOAD_PATH}/{datetime.now().strftime('%Y-%m-%d')}/{new_filename}"

        # 创建分片上传任务
        upload_id = bucket.init_multipart_upload(file_name).upload_id

        complete_data = BytesIO()

        # 读取文件并分片上传
        parts = []
        part_number = 1
        while True:
            chunk = await file.read(PART_SIZE)
            if not chunk:
                break

             # 保存 chunk 到完整数据
            complete_data.write(chunk)

            # 上传分片
            size = len(chunk)
            result = bucket.upload_part(file_name, upload_id, part_number, SizedFileAdapter(BytesIO(chunk), len(chunk)))
            part_crc = result.crc if hasattr(result, 'crc') else None  # 根据实际情况获取 part_crc

            part_info = PartInfo(part_number, result.etag, size, part_crc)
            parts.append(part_info)
      
            part_number += 1
            
        bucket.complete_multipart_upload(file_name, upload_id, parts)

        # 生成文件的访问 URL
        file_url = f"{STATIC_PREFIX}/{file_name}"

        complete_data.seek(0)
        # 获取文件信息
        imagewidth, imageheight, imagetype, imageframes = 0, 0, "", 0
        if file.content_type.startswith("image"):
            with Image.open(complete_data) as img:
                imagewidth, imageheight = img.size
                imagetype = img.format
                imageframes = getattr(img, 'n_frames', 1)

        return file_url, file_name, imagewidth, imageheight, imagetype, imageframes

    except exceptions.RequestError as e:
        raise HTTPException(status_code=400, detail=f"请求错误: {str(e)}")
    except exceptions.NoSuchBucket as e:
        raise HTTPException(status_code=400, detail=f"Bucket 不存在: {str(e)}")
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"文件上传失败: {str(e)}")


# 删除文件
async def delete_file(file_path: str):
    try:
        # 尝试删除对象
        result = bucket.delete_object(file_path)
         # 检查删除操作的状态
        if result.status != 204:
            log_admin_event(f"文件删除失败，状态码: {result.status}")

    except exceptions.RequestError as e:
        log_admin_event(f"文件删除失败{str(e)}")
    except exceptions.NoSuchBucket as e:
        log_admin_event(f"Bucket 不存在:{str(e)}")
    except Exception as e:
        log_admin_event(f"文件删除失败{str(e)}")

def get_url(file_path: str):
    return STATIC_PREFIX + "/" + file_path